﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Text;
using System.Threading.Tasks;

namespace TaskLiskFullscreen
{
 
    public class RenderSuite : IDisposable
    {
        private Graphics _g;
        private Bitmap _b;
        private bool disposedValue;

        public Bitmap Bitmap { get { return _b; } }
        public Graphics Graphics { get { return _g; } }

        public RenderSuite(int width,int height) { 
            _b = new Bitmap(width,height);
            _g = Graphics.FromImage(_b);
        }

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    _b.Dispose();
                    _g.Dispose();
                }

                disposedValue = true;
            }
        }


        public void Dispose()
        {
            
            Dispose(disposing: true);
            GC.SuppressFinalize(this);
        }
    }


    public class CachedObject<TKey,TValue>
    {
        private Func<TKey, TValue> _valueGenerator;
        private int maxCacheCount = 4;
        public CachedObject(Func<TKey,TValue> generator,int maxCount = 4) {
            this._valueGenerator = generator;
            this.maxCacheCount = maxCount;
            _cache = new Dictionary<TKey, CacheObjectEntry<TValue>>();
        }

        public TValue this[TKey index]
        {
            get { 
                return GetValueInternal(index);
            }
        }

        private Dictionary<TKey, CacheObjectEntry<TValue>> _cache;

        private TValue GetValueInternal(TKey key)
        {
            if (_cache.ContainsKey(key))
            {
                _cache[key].lastUse = DateTime.Now;
                return _cache[key].value;
            }
            else
            {
                var cache = new CacheObjectEntry<TValue>();
                cache.lastUse = DateTime.Now;
                cache.value = _valueGenerator(key);
                _cache.Add(key, cache);
                Console.WriteLine("Created object with key: "+key.ToString());
                RemoveOverflow();

                return cache.value;
            }
        }

        private void RemoveOverflow()
        {
            if(_cache.Count >= maxCacheCount * 2)
            {
                while(_cache.Count > maxCacheCount) {
                    var key = _cache.OrderBy(d => d.Value.lastUse).Select(d => d.Key).FirstOrDefault();
                    if(key != null)
                    {
                        var obj = _cache[key];
                        if(obj.value is IDisposable d)
                        {
                            d.Dispose();
                        }
                        _cache.Remove(key);
                        Console.WriteLine("Removed object with key: " + key.ToString());
                    }
                }
            }
        }
        
        private class CacheObjectEntry<TValue>
        {
            public TValue value;
            public DateTime lastUse;
        }

    }


}
